﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;

namespace socket客户端
{
    public partial class MainWindowViewModel : ObservableObject
    {

        /// <summary>
        /// IP地址
        /// </summary>
        [ObservableProperty]
        string iPAddressInfo;

        /// <summary>
        /// 端口号
        /// </summary>
        [ObservableProperty]
        string portInfo;

        /// <summary>
        /// 日志记录
        /// </summary>
        [ObservableProperty]
        public ObservableCollection<LogInfo> logList = new ObservableCollection<LogInfo>();

        /// <summary>
        /// 发送消息
        /// </summary>
        [ObservableProperty]
        string sendInfo;

        /// <summary>
        /// 当前socket
        /// </summary>
        public Socket ClientSocket { get; set; }


        /// <summary>
        /// 启动socket
        /// </summary>
        [RelayCommand]
        void StartSocket()
        {
            if (string.IsNullOrEmpty(IPAddressInfo) || string.IsNullOrEmpty(PortInfo))
            {
                return;
            }


            // 客户端连接服务器端
            // 创建Socket对象
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            // 连接服务器端
            try
            {
                socket.Connect(IPAddress.Parse(IPAddressInfo), int.Parse(PortInfo));

                ClientSocket = socket;
                AppendTextToLog($"服务器端:{socket.RemoteEndPoint.ToString()}已连接上");
            }
            catch (Exception ex)
            {
                MessageBox.Show("败了, 重新连接");
                return;
            }

            // 发送消息，接收消息
            ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveData), socket);
        }


        public void ReceiveData(object socket)
        {
            var CurrentSocket = socket as Socket;
            byte[] data = new byte[1024 * 1024];

            while (true) 
            {
                int len = 0;

                try
                {
                    len = CurrentSocket.Receive(data, 0, data.Length, SocketFlags.None);
                }
                catch (Exception ex)
                {
                    // 异常退出
                    AppendTextToLog($"服务端:{CurrentSocket.RemoteEndPoint.ToString()}非正常退出");

                    // 关闭连接
                    StopConnect();
                    return;
                }

                if (len <= 0)
                {
                    // 服务器端正常退出
                    AppendTextToLog($"服务器端:{CurrentSocket.RemoteEndPoint.ToString()}正常退出");
                    return;
                }

                // 对接收的到数据的第一个字节进行判断 1为字符串 2是闪屏 3是文件

                // 接收字符串
                if (data[0] == 1)
                {
                    ProcessRecieveString(data, CurrentSocket);
                }

                // 接收txt文件
                if (data[0] == 3)
                {
                    ProcessRecieveFile(data, CurrentSocket);
                }
                
            }
        }


        #region 处理接收的字符串
        private void ProcessRecieveString(byte[] data, Socket CurrentSocket)
        {
            if (data[0] == 1)
            {
                byte[] result = new byte[data.Length - 1];

                Buffer.BlockCopy(data, 1, result, 0, data.Length - 1);

                // 把接收到的数据放在文本框上去
                string str = Encoding.Default.GetString(result, 0, result.Length);
                AppendTextToLog($"接收服务器端:{CurrentSocket.RemoteEndPoint.ToString()}的消息是:{str}");
            }

        }

        #endregion


        #region

        private void ProcessRecieveFile(byte[] data, Socket CurrentSocket)
        {
            if (data[0] == 3)
            {
                byte[] result = new byte[data.Length - 1];

                Buffer.BlockCopy(data, 1, result, 0, data.Length - 1);

                string str = Encoding.Default.GetString(result, 0, result.Length);

                bool status = WriteFile.WriteFileByReceive(str);

                if (status)
                {
                    AppendTextToLog($"接收服务器端:{CurrentSocket.RemoteEndPoint.ToString()}的文件");
                }
            }
        }

        #endregion


        #region 处理闪屏

        private void ProcessSendFlashScreen(byte[] data, Socket CurrentSocket)
        {
            if (data[0] == 2)
            {
                
            }
        }

        #endregion


        /// <summary>
        /// 增加文本到日志
        /// </summary>
        /// <param name="log"></param>
        public void AppendTextToLog(string log)
        {
            Application.Current.Dispatcher.InvokeAsync(() =>
            {
                LogList.Add(new LogInfo() { Info = log, Time = DateTime.Now.ToString()});

            });
        }

        /// <summary>
        /// 关闭连接
        /// </summary>
        private void StopConnect()
        {
            try
            {
                if (ClientSocket.Connected)
                {
                    ClientSocket.Shutdown(SocketShutdown.Both);
                    ClientSocket.Close(100);
                }
            }
            catch (Exception)
            {

                throw;
            }
            
        }


        /// <summary>
        /// 发送信息
        /// </summary>
        [RelayCommand]
        void Send()
        {
            if (ClientSocket.Connected)
            {
                byte[] data = Encoding.Default.GetBytes(SendInfo);
                ClientSocket.Send(data, 0, data.Length, SocketFlags.None);

                // 清空发送区
                SendInfo = string.Empty;
            }
        }
    }
}
